package com.carrie.mdg.myviewtext.ui;

import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.DashPathEffect;
import android.graphics.LinearGradient;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.Shader;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.SparseArray;
import android.view.View;
import android.widget.ImageView;

import com.vincan.rotatecircleimageview.RotateCircleImageView;

public class RotateView  extends View{
    private static final ImageView.ScaleType SCALE_TYPE = ImageView.ScaleType.CENTER_CROP;

    private static final Bitmap.Config BITMAP_CONFIG = Bitmap.Config.ARGB_8888;
    private static final int COLORDRAWABLE_DIMENSION = 2;

    private static final int DEFAULT_BORDER_WIDTH = 0;
    private static final int DEFAULT_CIRCLE_BACKGROUND_COLOR = Color.TRANSPARENT;
    private static final boolean DEFAULT_BORDER_OVERLAY = false;

    private final RectF mDrawableRect = new RectF();
    private final RectF mBorderRect = new RectF();

    private final Matrix mShaderMatrix = new Matrix();
    private final Paint mBitmapPaint = new Paint();
    private final Paint mBorderPaint = new Paint();
    private final Paint mCircleBackgroundPaint = new Paint();

    private int mBorderWidth = DEFAULT_BORDER_WIDTH;
    private int mCircleBackgroundColor = DEFAULT_CIRCLE_BACKGROUND_COLOR;

    private Bitmap mBitmap;
    private BitmapShader mBitmapShader;
    private int mBitmapWidth;
    private int mBitmapHeight;

    private float mDrawableRadius;

    private ColorFilter mColorFilter;

    private boolean mReady;
    private boolean mSetupPending;
    private boolean mBorderOverlay;
    private boolean mDisableCircularTransformation;

    private static final int DEFAULT_BORDER_TRACK_START_COLOR = Color.parseColor("#4799FE");
    private static final int DEFAULT_BORDER_TRACK_END_COLOR = Color.parseColor("#19D7FD");
    private static final int DEFAULT_BORDER_ROTATE_DURATION = 1200;
    private static final int DEFAULT_BORDER_TRACK_DURATION = 2000;
    private static final int DEFAULT_CIRCLE_COLOR = DEFAULT_BORDER_TRACK_START_COLOR;
    private static final int DEFAULT_BORDER_PADDING = 0;
    private static final int DEFAULT_BORDER_COLORS_LENGTH = 50;
    private static final float SOLID_ARC_MARGIN_ANGLE = 6f;

    public enum BorderStyle {
        STILL,
        ROTATE
    }

    private final static SparseArray<RotateCircleImageView.BorderStyle> sBorderStyleArray = new SparseArray<RotateCircleImageView.BorderStyle>(2) {
        {
            append(0, RotateCircleImageView.BorderStyle.STILL);
            append(1, RotateCircleImageView.BorderStyle.ROTATE);
        }
    };
    private RotateCircleImageView.BorderStyle mBorderStyle = RotateCircleImageView.BorderStyle.STILL;

    private float mRotateAngle;
    private ValueAnimator mRotateValueAnimator;
    private int mBorderRotateDuration = DEFAULT_BORDER_ROTATE_DURATION;

    private int mBorderTrackDuration = DEFAULT_BORDER_TRACK_DURATION;
    private int mBorderTrackStartColor = DEFAULT_BORDER_TRACK_START_COLOR;
    private int mBorderTrackEndColor = DEFAULT_BORDER_TRACK_END_COLOR;

    private ValueAnimator mFirstSolidTrackValueAnimator;//0=>216
    private ValueAnimator mSecondSolidValueAnimator;//216<=>36
    private float mSolidTrackAngle;
    private Paint mSolidTrackPaint = new Paint();

    private ValueAnimator mFirstDottedTrackValueAnimator;//0=>360
    private ValueAnimator mSencondDottedTrackValueAnimator;//360<=>108
    private float mDottedTrackAngle;
    private Paint mDottedTrackPaint = new Paint();
    private DashPathEffect mDashPathEffect = new DashPathEffect(new float[]{1f, 15f}, 0f);

    private int[] mBorderColors = new int[]{DEFAULT_CIRCLE_COLOR};
    private int mBorderPadding = DEFAULT_BORDER_PADDING;

    public RotateView(Context context) {
        super(context);
        init();
    }

    public RotateView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public RotateView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        drawRotateBorder(canvas);
    }

    private void init(){
        setUp();
    }

    private void drawRotateBorder(Canvas canvas) {
        canvas.rotate(mRotateAngle, mBorderRect.centerX(), mBorderRect.centerY());//实线圆弧末端转动是通过旋转整个view来实现的
        canvas.drawArc(mBorderRect, 270f, mSolidTrackAngle, false, mSolidTrackPaint);
        canvas.drawArc(mBorderRect, 270f, mDottedTrackAngle, false, mDottedTrackPaint);
    }

    private void setUp(){
//        if (!mReady) {
//            mSetupPending = true;
//            return;
//        }

        if (getWidth() == 0 && getHeight() == 0) {
            return;
        }

//        if (mBitmap != null) {
//            mBitmapPaint.setAntiAlias(true);
//            mBitmapShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
//            mBitmapPaint.setShader(mBitmapShader);
//            mBitmapHeight = mBitmap.getHeight();
//            mBitmapWidth = mBitmap.getWidth();
//        }

        mBorderPaint.setStyle(Paint.Style.STROKE);
        mBorderPaint.setAntiAlias(true);
        mBorderPaint.setStrokeWidth(mBorderWidth);
        mBorderPaint.setStrokeCap(Paint.Cap.ROUND);

        mCircleBackgroundPaint.setStyle(Paint.Style.FILL);
        mCircleBackgroundPaint.setAntiAlias(true);
        mCircleBackgroundPaint.setColor(mCircleBackgroundColor);

        mBorderRect.set(calculateBounds());
        mBorderRect.inset(mBorderWidth / 2.0f, mBorderWidth / 2.0f);

        mDrawableRect.set(calculateBounds());
        if (mBorderPadding > 0) {
            mDrawableRect.inset(mBorderPadding, mBorderPadding);
        }
        if (!mBorderOverlay && mBorderWidth > 0) {
            mDrawableRect.inset(mBorderWidth - 1.0f, mBorderWidth - 1.0f);
        }
        mDrawableRadius = Math.min(mDrawableRect.height() / 2.0f, mDrawableRect.width() / 2.0f);

        Shader shader = new LinearGradient(0f, 0f, getWidth(),
                getHeight(), mBorderTrackStartColor, mBorderTrackEndColor, Shader.TileMode.CLAMP);
        mSolidTrackPaint.setShader(shader);
        mSolidTrackPaint.setStyle(Paint.Style.STROKE);
        mSolidTrackPaint.setAntiAlias(true);
        mSolidTrackPaint.setStrokeWidth(mBorderWidth);
        mSolidTrackPaint.setStrokeCap(Paint.Cap.ROUND);

        mDottedTrackPaint = new Paint(mSolidTrackPaint);
        mDottedTrackPaint.setPathEffect(mDashPathEffect);

        applyColorFilter();
        updateShaderMatrix();
        invalidate();
    }

    private RectF calculateBounds() {
        int availableWidth = getWidth() - getPaddingLeft() - getPaddingRight();
        int availableHeight = getHeight() - getPaddingTop() - getPaddingBottom();

        int sideLength = Math.min(availableWidth, availableHeight);

        float left = getPaddingLeft() + (availableWidth - sideLength) / 2f;
        float top = getPaddingTop() + (availableHeight - sideLength) / 2f;

        return new RectF(left, top, left + sideLength, top + sideLength);
    }

    private void applyColorFilter() {
        if (mBitmapPaint != null) {
            mBitmapPaint.setColorFilter(mColorFilter);
        }
    }

    private void updateShaderMatrix() {
        if (mBitmap == null) {
            return;
        }
        float scale;
        float dx = 0;
        float dy = 0;

        mShaderMatrix.set(null);

        if (mBitmapWidth * mDrawableRect.height() > mDrawableRect.width() * mBitmapHeight) {
            scale = mDrawableRect.height() / (float) mBitmapHeight;
            dx = (mDrawableRect.width() - mBitmapWidth * scale) * 0.5f;
        } else {
            scale = mDrawableRect.width() / (float) mBitmapWidth;
            dy = (mDrawableRect.height() - mBitmapHeight * scale) * 0.5f;
        }

        mShaderMatrix.setScale(scale, scale);
        mShaderMatrix.postTranslate((int) (dx + 0.5f) + mDrawableRect.left, (int) (dy + 0.5f) + mDrawableRect.top);

        mBitmapShader.setLocalMatrix(mShaderMatrix);
    }

}
